/*
* $Id: TableDrawer.cpp 7 2010-01-04 16:22:07Z volok-aleksej@yandex.ru $
*
* Copyright 2009 by Volokitin Alexey
* All rights reserved
*
*/
#include "Common/include.h"
#include "TableDrawer.h"
#include "TableHeader.h"

#define SIZE_SCROLL		17

CTableDrawer::CTableDrawer()
: m_nPosYFirstCel(0), m_nPosYFirstVisibleCel(0), m_pFirstVisibleRow(NULL),
m_pSelectRow(NULL), m_pCurResizeHeader(NULL), m_bResizeHeader(false),
m_bResizeRow(false), m_pCurResizeRow(NULL){}
CTableDrawer::~CTableDrawer(){
	ResetTable();
}

void CTableDrawer::InitTable(){
	if(m_aCels.size())
		m_pFirstVisibleRow = m_aCels[0];
	m_nPosYFirstVisibleCel = 0;
}
void CTableDrawer::ResetTable(){
	m_HeaderRow.Clear();
	for(std::vector<CTableCelRow*>::iterator it = m_aCels.begin(); it != m_aCels.end(); it++)
		delete *it;
	m_aCels.clear();
	m_resizeHelper.Reset();
	m_pFirstVisibleRow = NULL;
	m_pSelectRow = NULL;
	m_pCurResizeRow = NULL;
	m_pCurResizeHeader = NULL;
}
void CTableDrawer::SetFirstCelPosY(int pos){
	m_nPosYFirstCel = pos;
}
bool CTableDrawer::IsSelectRow(){
	return m_pSelectRow != NULL;
}
CTableCelRow* CTableDrawer::GetSelectRow(){
	return m_pSelectRow;
}
int CTableDrawer::GetHeightTable(){
	return m_resizeHelper.GetSize() + m_HeaderRow.GetHeightHeader();
}
bool CTableDrawer::IsResizeHeader(){
	return m_bResizeHeader;
}
bool CTableDrawer::IsBeginResizeHeader(CPoint pos){
	return IsResizeHeader() || m_HeaderRow.IsSetCursor(pos);
}
CRect CTableDrawer::GetResizeHeaderRect(){
	if(!IsResizeHeader())
		return CRect(0, 0, 0, 0);
	return CRect(m_pCurResizeHeader->GetPos(), m_pCurResizeHeader->GetSize());
}
bool CTableDrawer::IsBeginResizeRow(CPoint pos){
	if(IsResizeRow())
		return true;
	if(pos.x > m_HeaderRow.GetWidthTable())
		return false;
	for(CTableCelRow* row = m_pFirstVisibleRow; row; row = row->m_pNext){
		if(row->GetYPos() > pos.y)
			break;
		if(row->IsSetCursor(pos))
			return true;
	}
	return false;
}
bool CTableDrawer::IsResizeRow(){
	return m_bResizeRow;
}

void CTableDrawer::PaintTable(CDC* dc, CRect rect){
	CDC cdc;
	cdc.CreateCompatibleDC(dc);
	CBitmap bitmapTable;
	bitmapTable.CreateCompatibleBitmap(dc, rect.Size().cx, rect.Size().cy);
	HGDIOBJ bitmapOld = cdc.SelectObject(bitmapTable);
	CBrush brush;
	brush.CreateSolidBrush(GetSysColor(COLOR_3DFACE));
	cdc.FillRect(CRect(CPoint(0, 0), rect.Size()), &brush);
	brush.DeleteObject();

	int cy = m_nPosYFirstVisibleCel + m_HeaderRow.GetHeightHeader();
	for(CTableCelRow* row = m_pFirstVisibleRow; row; row = row->m_pNext){
		row->SetPosY(cy);
		cy += row->GetCY();
		if(!row->Paint(&cdc, CRect(CPoint(0, 0), rect.Size())))
			break;
	}
	m_HeaderRow.Paint(&cdc, CRect(CPoint(0, 0), rect.Size()));

	dc->BitBlt(rect.left, rect.top, rect.Size().cx, rect.Size().cy, &cdc, 0, 0, SRCCOPY);
	cdc.SelectObject(bitmapOld);
	bitmapTable.DeleteObject();
	cdc.DeleteDC();
}

void CTableDrawer::SelectRow(CPoint point){
	if(point.x < m_HeaderRow.GetWidthTable() && point.y > m_HeaderRow.GetHeightHeader()){
		if(m_pSelectRow)
			m_pSelectRow->Select(false);
		m_pSelectRow = NULL;
		for(CTableCelRow* row = m_pFirstVisibleRow; row; row = row->m_pNext){
			if(point.y > row->GetYPos() && point.y < row->GetYPos() + row->GetCY()){
				m_pSelectRow = row;
				m_pSelectRow->Select(true);
				break;
			}
		}
	}
}

bool CTableDrawer::BeginResizeHeader(CPoint pos){
	if(m_bResizeHeader || m_HeaderRow.IsSetCursor(pos, &m_pCurResizeHeader))
		m_bResizeHeader = true;
	return m_bResizeHeader;
}
void CTableDrawer::ResizeHeader(CSize size){
	if(!IsResizeHeader())
		return;
	m_pCurResizeHeader->SetSize(size);
	NormalizeHeader();
}
void CTableDrawer::EndResizeHeader(){
	m_pCurResizeHeader = NULL;
	m_bResizeHeader = false;
}

bool CTableDrawer::BeginResizeRow(CPoint pos){
	for(CTableCelRow* row = m_pFirstVisibleRow; row; row = row->m_pNext){
		if(row->GetYPos() > pos.y)
			break;
		if(row->IsSetCursor(pos)){
			m_pCurResizeRow = row;
			m_bResizeRow = true;
			m_resizeHelper.BeginResizeRow(pos.y - m_HeaderRow.GetHeightHeader());
			return true;
		}
	}
	return false;
}
void CTableDrawer::ResizeRow(int size){
	if(!IsResizeRow())
		return;
	m_pCurResizeRow->SetCY(size);
	m_resizeHelper.SetSize(size);
}
void CTableDrawer::EndResizeRow(){
	m_pCurResizeRow = NULL;
	m_bResizeRow = false;
	m_resizeHelper.EndResizeRow();
}

void CTableDrawer::UpgradeFirstVisiblePosY(int newPos){
	int pos = m_resizeHelper.GetPosRow(newPos, m_nPosYFirstVisibleCel);
	m_pFirstVisibleRow = m_aCels[pos];
	m_nPosYFirstCel = -newPos;
}

void CTableDrawer::NormalizeHeader(){
	int nOldHeightHeader = m_HeaderRow.GetHeightHeader();
	m_HeaderRow.NormalizeHeader();
}

void CTableDrawer::AddCelRow(CTableCelRow *row){
	if(m_aCels.size()){
		row->m_pBack = m_aCels.back();
		row->m_pBack->m_pNext = row;
	}
	m_resizeHelper.AddSizeRow(row->GetCY());
	m_aCels.push_back(row);
}

int CTableDrawer::GetWidthTable(){
	return m_HeaderRow.GetWidthTable();
}

void CTableDrawer::SetPosX(int pos){
	m_HeaderRow.SetPosX(pos);
}

tableHeader* CTableDrawer::AddHeader(const std::tstring& strName, int nId){
	return m_HeaderRow.AddHeader(strName, nId);
}

void CTableDrawer::GetResizeRowPosSize(int* nPos, int* nSize){
	if(nPos)
		*nPos = m_pCurResizeRow->GetYPos();
	if(nSize)
		*nSize = m_pCurResizeRow->GetCY();
}

bool CTableDrawer::IsValidDrawer(Drawer::typeDrawer nType){
	return nType == Drawer::table;
}